#!/bin/bash

set -o errexit

test_dir=$(realpath $(dirname $0))
. ${test_dir}/../functions

set_debug

get_container_options() {
	backup_name=$1
	cluster_name=$2

	backup_options=$(kubectl_bin get pxc-backup "$backup_name" -o jsonpath='{.spec.containerOptions}')
	if [[ -n $backup_options ]]; then
		echo "$backup_options"
		return
	fi

	storage_name=$(kubectl_bin get pxc-backup "$backup_name" -o jsonpath='{.spec.storageName}')
	storage_options=$(kubectl_bin get pxc "$cluster_name" -o jsonpath="{.spec.backup.storages.$storage_name.containerOptions}")
	if [[ -n $storage_options ]]; then
		echo "$storage_options"
		return
	fi
}

run_recovery_from_source() {
	local storage_type=${1:-s3}
	local backup_name=${2:-on-demand-backup-aws-s3}
	local remove_bucket_or_container_name=${3:-""}
	local remove_prefix_from_destination=${4:-""}

	remove_options=""
	if [ -n "$remove_bucket_or_container_name" ]; then
		remove_options=", .$storage_type.bucket, .$storage_type.container"
	fi

	remove_prefix='test'
	if [ -n "${remove_prefix_from_destination}" -a -z "${remove_bucket_or_container_name}" ]; then
		remove_prefix="$storage_type"
	fi

	desc "$storage_type restore with backup source"
	restore_name="on-demand-backup-$storage_type"

	restore_json=$(jq ".metadata.name=\"$restore_name\"" "$test_dir/conf/restore-from-source-backup.json")

	container_options=$(get_container_options "$backup_name" "$cluster")
	if [[ -n $container_options ]]; then
		restore_json=$(echo "$restore_json" | jq ".spec.containerOptions=$container_options")
	fi

	backup_source_json=$(kubectl_bin get pxc-backup "$backup_name" -o json \
		| jq -c '.status | {'"$storage_type"', destination} | del(.'"$storage_type"'.endpointUrl, .'"$storage_type"'.storageClass '"$remove_options"')' \
		| $sed "s|$remove_prefix://||")
	echo "$restore_json" \
		| jq ".spec.backupSource=$backup_source_json" \
		| kubectl_bin apply -f -

	sleep 30
	wait_for_running "$cluster-proxysql" 1
	wait_for_running "$cluster-pxc" 3
	sleep 30
	desc 'check data after backup from source'
	compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h $cluster-pxc-0.$cluster-pxc -uroot -proot_password"
	compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h $cluster-pxc-1.$cluster-pxc -uroot -proot_password"
	compare_mysql_cmd "select-1" "SELECT * from myApp.myApp;" "-h $cluster-pxc-2.$cluster-pxc -uroot -proot_password"
}

# If backup upload was started and failed for some reason the cloud storage should be cleaned up during second try
delete_backup_pod() {
	local backup_name=$1

	desc "Delete ${backup_name} pod during SST"
	echo "Waiting for ${backup_name} pod to become Running"
	sleep 1
	kubectl_bin wait --for=jsonpath='{.status.phase}'=Running pod --selector=percona.com/backup-job-name=xb-${backup_name} --timeout=120s

	backup_pod=$(kubectl_bin get pods --selector=percona.com/backup-job-name=xb-${backup_name} -o jsonpath='{.items[].metadata.name}')

	echo "Deleting pod/${backup_pod} during SST upload"
	kubectl logs -f ${backup_pod} | while IFS= read -r line; do
		if [[ $line =~ \.ibd\. ]]; then
			kubectl delete pod --force ${backup_pod}
			break
		fi
	done

}

check_cloud_storage_cleanup() {
	local backup_name=$1

	desc "Check storage cleanup of ${backup_name}"
	if [[ $(kubectl_bin get events --field-selector involvedObject.kind=Job,involvedObject.name=xb-${backup_name} | grep -c "Created pod") == '1' ]]; then
		echo "There should be 2+ pods started by job. First backup finished too quick"
		exit 1
	fi
	local backup_pod=$(kubectl_bin get pods --selector=percona.com/backup-job-name=xb-${backup_name} -o jsonpath='{.items[].metadata.name}')
	if [[ $IMAGE_PXC =~ 5\.7 ]]; then
		# There are 2 deletes during backup: $backup_dir_sst_info & $backup_dir
		deletes_num=$(kubectl_bin logs ${backup_pod} | grep -c 'Delete completed.')
		if [[ ${deletes_num} -ge '2' ]]; then
			echo "Bucket cleanup was successful"
		else
			echo "Something went wrong. Delete was performed for $deletes_num. Expected: 2."
			kubectl_bin logs ${backup_pod}
			exit 1
		fi
	else
		if kubectl_bin logs ${backup_pod} | grep 'Object deleted successfully before attempt 1. Exiting.'; then
			echo "Something went wrong. Delete was not performed."
			kubectl_bin logs ${backup_pod}
			exit 1
		else
			echo "Clenup was performed."
		fi
	fi
}

run_backup_with_delete() {
	local backup_name=$1

	desc "make backup ${backup_name}"
	kubectl_bin apply \
		-f $test_dir/conf/${backup_name}.yml
	delete_backup_pod ${backup_name}
	wait_backup "${backup_name}"
	check_cloud_storage_cleanup "${backup_name}"
}

main() {
	if [ -n "$SKIP_REMOTE_BACKUPS" ]; then
		echo "Skipping test because SKIP_REMOTE_BACKUPS variable is set!"
		exit 0
	else
		create_infra $namespace

		cluster="demand-backup-cloud"
		spinup_pxc "$cluster" "$test_dir/conf/$cluster.yml"

		backup_name_aws="on-demand-backup-aws-s3"
		backup_name_gcp="on-demand-backup-gcp-cs"
		backup_name_azure="on-demand-backup-azure-blob"

		desc "Run backup ${backup_name_aws} for $cluster cluster"
		run_backup_with_delete "${backup_name_aws}"

		desc "Run recovery from s3 for $cluster cluster"
		run_recovery_check "$cluster" "${backup_name_aws}"

		desc "Run recovery from s3 source with default options"
		run_recovery_from_source

		desc 'Run recovery from s3 source without s3:// prefix in destination'
		run_recovery_from_source 's3' "${backup_name_aws}" '' 'remove_prefix_from_destination'

		desc 'Run recovery from s3 source without bucket option'
		run_recovery_from_source 's3' "${backup_name_aws}" 'remove_bucket_name'
		compare_kubectl job.batch/xb-"${backup_name_aws}"
		compare_kubectl job.batch/restore-job-on-demand-backup-s3-demand-backup-cloud

		desc "Run backup ${backup_name_gcp} for $cluster cluster"
		run_backup_with_delete "${backup_name_gcp}"

		desc "Run recovery from s3 for $cluster cluster"
		run_recovery_check "$cluster" "${backup_name_gcp}"

		desc "Run backup ${backup_name_azure} for $cluster cluster"
		run_backup_with_delete "${backup_name_azure}"

		desc "Run recovery from azure for $cluster cluster"
		run_recovery_check "$cluster" "${backup_name_azure}"

		desc "Run recovery from azure source with default options"
		run_recovery_from_source 'azure' "${backup_name_azure}"

		desc 'Run recovery from azure source without azure:// prefix in destination'
		run_recovery_from_source 'azure' "${backup_name_azure}" '' 'remove_prefix_from_destination'

		desc 'Run recovery from azure source without container option'
		run_recovery_from_source 'azure' "${backup_name_azure}" 'remove_container_name'
		compare_kubectl job.batch/xb-"${backup_name_azure}"
		compare_kubectl job.batch/restore-job-on-demand-backup-azure-demand-backup-cloud

		backup_dest_aws=$(kubectl_bin get pxc-backup "$backup_name_aws" -o jsonpath='{.status.destination}' | sed -e 's/.json$//' | cut -c 6-)
		backup_dest_gcp=$(kubectl_bin get pxc-backup "$backup_name_gcp" -o jsonpath='{.status.destination}' | sed -e 's/.json$//' | cut -c 6-)
		backup_dest_azure=$(kubectl_bin get pxc-backup "$backup_name_azure" -o jsonpath='{.status.destination}' | sed -e 's/.json$//' | cut -c 9-)

		desc "Check backup existence"
		check_backup_existence "https://s3.amazonaws.com/${backup_dest_aws}.sst_info/sst_info.00000000000000000000" "aws-s3"
		check_backup_existence "https://storage.googleapis.com/${backup_dest_gcp}.sst_info/sst_info.00000000000000000000" "gcp-cs"
		check_backup_existence "https://engk8soperators.blob.core.windows.net/${backup_dest_azure}.sst_info/sst_info.00000000000000000000" "azure-blob"

		kubectl_bin delete pxc-backup --all

		desc "Check backup deletion"
		check_backup_deletion "https://s3.amazonaws.com/${backup_dest_aws}.sst_info/sst_info.00000000000000000000" "aws-s3"
		check_backup_deletion "https://storage.googleapis.com/${backup_dest_gcp}.sst_info/sst_info.00000000000000000000" "gcp-cs"
		check_backup_deletion "https://engk8soperators.blob.core.windows.net/${backup_dest_azure}.sst_info/sst_info.00000000000000000000" "azure-blob"

		if [ "$EKS" = 1 ]; then
			backup_name_aws_iam="on-demand-backup-aws-s3-iam"
			desc "Run backup ${backup_name_aws_iam} for $cluster cluster using IAM"
			run_backup_with_delete "${backup_name_aws_iam}"
			desc "Check backup existence for $backup_name_aws_iam"
			backup_dest_aws_iam=$(kubectl_bin get pxc-backup "$backup_name_aws_iam" -o jsonpath='{.status.destination}' | sed -e 's/.json$//' | cut -c 6-)
			check_backup_existence "https://s3.amazonaws.com/${backup_dest_aws_iam}.sst_info/sst_info.00000000000000000000" "aws-s3-iam"
		fi

		destroy $namespace
		desc "test passed"
	fi
}
main
